package com.wwt.blog.aop;

import com.alibaba.fastjson.JSON;
import com.wwt.blog.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect   //缓存切面
@Component
@Slf4j
public class CacheAspect {
    @Autowired
    RedisTemplate<String,String > redisTemplate;
    //抽取切点
    @Pointcut("@annotation(com.wwt.blog.aop.Cache)")
    public void pointCut(){}

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //将请求方法的类名 方法名 参数列表拼接起来作为redis的Key
        Signature signature = pjp.getSignature(); //获取请求方法的签名  方法名+参数列表
        String methodName = signature.getName();  //获取请求方法的方法名
        String className = pjp.getTarget().getClass().getSimpleName(); //获取方法名

        Class[] paramType = new Class[pjp.getArgs().length];  //获取请求参数的类型  先定义数组长度
        Object[] args=pjp.getArgs();   //获取参数列表
        String paramString=" ";
        for (int i = 0; i <args.length ; i++) {
            if (args[i]!=null){
                paramString+= JSON.toJSONString(args[i]);
                paramType[i]=args[i].getClass();
            }else
                paramType[i]=null;
        }
        if(!paramString.isEmpty()){
            paramString = DigestUtils.md5Hex(paramString);

        }
        Method method = pjp.getSignature().getDeclaringType().getMethod(methodName, paramType);
        //获取注释
        Cache annotation = method.getAnnotation(Cache.class);
        long expire = annotation.expire();
        String value = annotation.value();
        //开始拼接redis的key
        String redisKey=value +":"+className+":"+methodName+":"+paramString;
        //先判断读取的内容是否在redis中
        String  result = redisTemplate.opsForValue().get(redisKey);
        if(result!=null){
            log.info("走了缓存*******");
         return   JSON.parseObject(result,Result.class);
        }
        Object methodResult = pjp.proceed();//查找内容缓存中找不到  执行后续程序 结果存入redis缓存
        redisTemplate.opsForValue().set(redisKey,JSON.toJSONString(methodResult),expire, TimeUnit.MILLISECONDS);
        return methodResult;
    }
}
